package com.start.autumn.config;

import com.alibaba.ttl.threadpool.TtlExecutors;
import com.start.autumn.config.properties.ExecutorProperties;
import com.start.autumn.constant.ThreadConstant;
import com.start.autumn.springUtils.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@EnableConfigurationProperties(ExecutorProperties.class)
@Configuration
@Slf4j
public class ThreadPoolConfig {
    @Resource
    private ExecutorProperties properties;

    @Value("${spring.application.name}")
    private String E_COMMON_EXECUTOR_NAME;

    @Bean(ThreadConstant.THREAD_POOL_NAME)
    public Executor threadPoolTaskExecutor() {
        log.info("ThreadPoolTaskExecutor init...");
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(properties.getCorePoolSize());
        taskExecutor.setMaxPoolSize(properties.getMaxPoolSize());
        taskExecutor.setQueueCapacity(properties.getQueueCapacity());
        taskExecutor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
        taskExecutor.setThreadNamePrefix(String.format("%s-executor-log-", E_COMMON_EXECUTOR_NAME));
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        taskExecutor.initialize();
        return TtlExecutors.getTtlExecutor(taskExecutor);
    }

    @PreDestroy
    public void destroy() {
        ThreadPoolTaskExecutor executor = SpringUtil.getBean(ThreadConstant.THREAD_POOL_NAME, ThreadPoolTaskExecutor.class);
        if (executor != null && executor.getThreadPoolExecutor().isShutdown()) {
            executor.shutdown();
            try {
                if (!executor.getThreadPoolExecutor().awaitTermination(1000, java.util.concurrent.TimeUnit.MILLISECONDS)) {
                    executor.getThreadPoolExecutor().shutdownNow();
                }
            } catch (InterruptedException ie) {
                log.error("ThreadPoolTaskExecutor destroy error:{}", ie.getMessage());
                executor.getThreadPoolExecutor().shutdown();
                Thread.currentThread().interrupt();
            }
        }
    }

}
